import { db, type Snapshot } from '@/utils/database'
import type { IndexableTypeArray } from 'dexie'
import { useFormulaEditor } from './formulaEditor'

export interface EditorStateTick {
  snapshotCursor: number
  snapshotLength: number
  savingSnapshotCursor: number
}

export const useSnapshotStore = defineStore('snapshot', {
  state: (): EditorStateTick => ({
    snapshotCursor: -1, // 历史快照指针
    snapshotLength: 0, // 历史快照长度
    savingSnapshotCursor: 0, // 保存时候的历史快照指针
  }),
  getters: {
    canUndo(state) {
      return state.snapshotCursor > 0
    },
    canRedo(state) {
      return state.snapshotCursor < state.snapshotLength - 1
    },
    // 是否未保存
    isSaved(state) {
      return (
        state.snapshotLength > 0 &&
        state.savingSnapshotCursor !== state.snapshotCursor
      )
    },
  },
  actions: {
    setSnapshotCursor(cursor: number) {
      this.snapshotCursor = cursor
    },
    setSnapshotLength(length: number) {
      this.snapshotLength = length
    },
    setSavingSnapshotCursor(cursor: number) {
      this.savingSnapshotCursor = cursor
    },
    async initSnapshotDatabase() {
      const formulaStore = useFormulaEditor()
      const snapshot = {
        index: 0,
        elements: JSON.parse(JSON.stringify(formulaStore.elements)),
      }
      const res = await db.formulas.add(snapshot)
      console.log(res, 1234)

      this.setSnapshotCursor(0)
      this.setSnapshotLength(1)
    },
    async addSnapshot() {
      const formulaStore = useFormulaEditor()
      const allKeys = await db.formulas.orderBy('id').keys()

      const needDeleteKeys: IndexableTypeArray = []

      // 记录需要删除的快照ID
      // 若当前快照指针不处在最后一位，那么再添加快照时，应该将当前指针位置后面的快照全部删除，对应的实际情况是：
      // 用户撤回多次后，再进行操作（添加快照），此时原先被撤销的快照都应该被删除
      if (
        this.snapshotCursor >= 0 &&
        this.snapshotCursor < allKeys.length - 1
      ) {
        needDeleteKeys.length = 0
        needDeleteKeys.push(...allKeys.slice(this.snapshotCursor + 1))
      }

      const snapshot = {
        index: this.snapshotLength,
        elements: JSON.parse(JSON.stringify(formulaStore.elements)),
      }
      await db.formulas.add(snapshot)

      // 计算当前快照长度，用于设置快照指针的位置（此时指针应该处在最后一位，即：快照长度 - 1）
      let snapshotLength = allKeys.length - needDeleteKeys.length + 1
      // 快照数量超过长度限制时，应该将头部多余的快照删除
      const snapshotLengthLimit = 20
      if (snapshotLength > snapshotLengthLimit) {
        needDeleteKeys.push(allKeys[0])
        snapshotLength--
      }

      if (snapshotLength >= 2) {
        db.formulas.update(allKeys[snapshotLength - 2] as number, {
          index: this.snapshotLength,
        })
      }

      await db.formulas.bulkDelete(needDeleteKeys as number[])

      this.setSnapshotCursor(snapshotLength - 1)
      this.setSnapshotLength(snapshotLength)
    },
    async unDo() {
      if (!this.canUndo) return

      const formulaStore = useFormulaEditor()

      const snapshotCursor = this.snapshotCursor - 1
      const snapshots: Snapshot[] = await db.formulas.orderBy('id').toArray()
      const snapshot = snapshots[snapshotCursor]

      formulaStore.setElements(snapshot.elements)
      this.setSnapshotCursor(snapshotCursor)
    },
    async reDo() {
      if (!this.canRedo) return

      const formulaStore = useFormulaEditor()

      const snapshotCursor = this.snapshotCursor + 1
      const snapshots: Snapshot[] = await db.formulas.orderBy('id').toArray()
      const snapshot = snapshots[snapshotCursor]

      formulaStore.setElements(snapshot.elements)
      this.setSnapshotCursor(snapshotCursor)
    },
  },
})
